﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Media;
using System.Windows.Shapes;
using GBL.Repository.Resources;
using GBlasonLogic.Helpers;

namespace GBlasonLogic.Tools
{
    public class GeometryTools
    {
        /// <summary>
        /// Gets the geometry from the constraints.CurrentGeometry.
        /// </summary>
        /// <param name="constraints">The constraints.</param>
        /// <returns>the path created from the string stored in the constraints</returns>
        /// <exception cref="ArgumentException">if constraints doesn't have a valid ParentGeometry</exception>
        /// <exception cref="ArgumentNullException">if constraints is null</exception>
        public static Geometry GetGeometryFromConstraints(ConstraintSet constraints)
        {
            if (constraints == null)
                throw new ArgumentNullException("constraints");
            var geo = Geometry.Parse(constraints.CurrentGeometry);
            if (geo == null)
                throw new ArgumentException("constraints");
            return geo;
        }

        public static Path PerformGeometry(ConstraintSet parentConstraint, ConstraintDivisionSet areaToGet)
        {
            var parentGeo = GetGeometryFromConstraints(parentConstraint);
            return CreatePath(parentGeo, areaToGet.DivisionPosition);
        }

        private static Path CreatePath(Geometry parent, Points point)
        {
            var geo = point.GetGeometry();
            return new Path
            {
                Data =
                new CombinedGeometry(GeometryCombineMode.Intersect, geo.Invoke(parent), parent)
                .GetFlattenedPathGeometry()
            };
        }


        #region geometry functions

        internal static Geometry GetBottomTop(Geometry originalGeometry)
        {
            var halfHeight = originalGeometry.Bounds.Height / 2;

            return new RectangleGeometry(
                new Rect(
                    originalGeometry.Bounds.TopLeft.X,
                    originalGeometry.Bounds.TopLeft.Y,
                    originalGeometry.Bounds.Width,
                    halfHeight));
        }

        internal static Geometry GetBottomHalf(Geometry originalGeometry)
        {
            var halfHeight = originalGeometry.Bounds.Height / 2;

            return new RectangleGeometry(
                new Rect(
                    originalGeometry.Bounds.TopLeft.X,
                    originalGeometry.Bounds.TopLeft.Y + halfHeight,
                    originalGeometry.Bounds.Width,
                    halfHeight));
        }

        internal static Geometry GetLeftHalf(Geometry originalGeometry)
        {
            var halfWidth = originalGeometry.Bounds.Width / 2;

            return new RectangleGeometry(
                new Rect(
                    originalGeometry.Bounds.TopLeft.X,
                    originalGeometry.Bounds.TopLeft.Y,
                    halfWidth,
                    originalGeometry.Bounds.Height));
        }

        internal static Geometry GetRightHalf(Geometry originalGeometry)
        {
            var halfWidth = originalGeometry.Bounds.Width / 2;

            return new RectangleGeometry(
                new Rect(
                    originalGeometry.Bounds.TopLeft.X + halfWidth,
                    originalGeometry.Bounds.TopLeft.Y,
                    halfWidth,
                    originalGeometry.Bounds.Height));
        }

        internal static Geometry GetBottomLeftHalf(Geometry originalGeometry)
        {
            var segments = new List<PathSegment>(2)
                {
                    new LineSegment(originalGeometry.Bounds.BottomRight, false),
                    new LineSegment(originalGeometry.Bounds.BottomLeft, false)
                };
            var fig = new List<PathFigure> { new PathFigure(originalGeometry.Bounds.TopLeft, segments, true) };
            return new PathGeometry(fig);
        }

        internal static Geometry GetBottomRightHalf(Geometry originalGeometry)
        {
            var segments = new List<PathSegment>(2)
                {
                    new LineSegment(originalGeometry.Bounds.BottomRight, false),
                    new LineSegment(originalGeometry.Bounds.BottomLeft, false)
                };
            var fig = new List<PathFigure> { new PathFigure(originalGeometry.Bounds.TopRight, segments, true) };
            return new PathGeometry(fig);
        }

        internal static Geometry GetTopRightHalf(Geometry originalGeometry)
        {
            var segments = new List<PathSegment>(2)
                {
                    new LineSegment(originalGeometry.Bounds.TopRight, false),
                    new LineSegment(originalGeometry.Bounds.BottomRight, false)
                };
            var fig = new List<PathFigure> { new PathFigure(originalGeometry.Bounds.TopLeft, segments, true) };
            return new PathGeometry(fig);
        }

        internal static Geometry GetTopLeftHalf(Geometry originalGeometry)
        {
            var segments = new List<PathSegment>(2)
                {
                    new LineSegment(originalGeometry.Bounds.TopRight, false),
                    new LineSegment(originalGeometry.Bounds.BottomLeft, false)
                };
            var fig = new List<PathFigure> { new PathFigure(originalGeometry.Bounds.TopLeft, segments, true) };
            return new PathGeometry(fig);
        }

        internal static Geometry GetDiagonalLeft(Geometry originalGeometry)
        {
            var middle = new Point(originalGeometry.Bounds.Width / 2, originalGeometry.Bounds.Height / 2);
            var segments = new List<PathSegment>(2)
                {
                    new LineSegment(middle, false),
                    new LineSegment(originalGeometry.Bounds.BottomLeft, false)
                };
            var fig = new List<PathFigure> { new PathFigure(originalGeometry.Bounds.TopLeft, segments, true) };
            return new PathGeometry(fig);
        }

        internal static Geometry GetDiagonalBottom(Geometry originalGeometry)
        {
            var middle = new Point(originalGeometry.Bounds.Width / 2, originalGeometry.Bounds.Height / 2);
            var segments = new List<PathSegment>(2)
                {
                    new LineSegment(middle, false),
                    new LineSegment(originalGeometry.Bounds.BottomRight, false)
                };
            var fig = new List<PathFigure> { new PathFigure(originalGeometry.Bounds.BottomLeft, segments, true) };
            return new PathGeometry(fig);
        }

        internal static Geometry GetDiagonalRight(Geometry originalGeometry)
        {
            var middle = new Point(originalGeometry.Bounds.Width / 2, originalGeometry.Bounds.Height / 2);
            var segments = new List<PathSegment>(2)
                {
                    new LineSegment(middle, false),
                    new LineSegment(originalGeometry.Bounds.BottomRight, false)
                };
            var fig = new List<PathFigure> { new PathFigure(originalGeometry.Bounds.TopRight, segments, true) };
            return new PathGeometry(fig);
        }

        internal static Geometry GetDiagonalTop(Geometry originalGeometry)
        {
            var middle = new Point(originalGeometry.Bounds.Width / 2, originalGeometry.Bounds.Height / 2);
            var segments = new List<PathSegment>(2)
                {
                    new LineSegment(middle, false),
                    new LineSegment(originalGeometry.Bounds.TopRight, false)
                };
            var fig = new List<PathFigure> { new PathFigure(originalGeometry.Bounds.TopLeft, segments, true) };
            return new PathGeometry(fig);
        }
        #endregion

    }
}
